/*********************************************************************************
  *FileName:  nsuc16xx_adc.c
  *Version:  V1.0
  *Date: 2023-09-21
****************************************Includes***********************************/
#include "nsuc16xx_adc.h"

/***************************************Variables***********************************/

/***************************************Functions***********************************/

/**
  * @brief  Initializes the ADCx peripheral according to the specified parameters
  *         in the ADC_InitStruct.
  * @param  ADCx: Select the ADC peripheral.
  * @param  ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains
  *         the configuration information for the specified ADC peripheral.
  * @retval None
  */
void ADC_Init(ADC_TypeDef *ADCx, ADC_InitTypeDef *ADC_InitStruct)
{
    ADCx->CR_b.CKSEL = ADC_InitStruct->ADC_ClockSource;
    ADCx->CR_b.TSRC = ADC_InitStruct->ADC_TrigSource;
    ADCx->SCR_b.ONDLY = ADC_InitStruct->ADC_OnDelayTimeCyecles;
    ADCx->SCR_b.STABLE = ADC_InitStruct->ADC_StableTimeCyecles;
    ADCx->SCR_b.CONV = ADC_InitStruct->ADC_ConvTimeCyecles;
    ADCx->SCR_b.SAMP = ADC_InitStruct->ADC_SampleTimeCyecles;
    ADCx->TCR_b.SIGEN = ADC_InitStruct->ADC_ConvMode;
    ADCx->TCR_b.REFSEL = ADC_InitStruct->ADC_RefVoltageSource;
}

/**
  * @brief  ADC queue configuration function.
  * @param  ADCx: Select the ADC peripheral.
  * @param  ADC_QueueRank: Specifies the ADC queue to be registered.
  *   This parameter can be any combination of ADC_QueueRankx where x can be (1..8).
  * @param  ADC_Channel: Specifies the ADC channel to be configured.
  * @param  ADC_PGA: Specifies the ADC PGA to be configured.
  * @param  ADC_State: new state of the ADCx peripheral.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void ADC_QueueConfig(ADC_TypeDef *ADCx, uint8_t ADC_QueueRank, uint8_t ADC_Channel, uint8_t ADC_PGA, uint8_t ADC_State)
{
    uint8_t temp = (ADC_State << 7) | (ADC_PGA << 4) | ADC_Channel;
    if (ADC_QueueRank <= 3)
    {
        ADCx->QCR1 &= ~((uint32_t)0xFF << ((uint32_t)((uint32_t)ADC_QueueRank & (uint32_t)0x03) * 8));
        ADCx->QCR1 |= ((uint32_t)(temp) << ((uint32_t)((uint32_t)ADC_QueueRank & (uint32_t)0x03) * 8));
    }
    else
    {
        ADCx->QCR2 &= ~((uint32_t)0xFF << ((uint32_t)((uint32_t)(ADC_QueueRank - 4) & (uint32_t)0x03) * 8));
        ADCx->QCR2 |= ((uint32_t)(temp) << ((uint32_t)((uint32_t)(ADC_QueueRank - 4) & (uint32_t)0x03) * 8));
    }
}

/**
  * @brief  Enables or disables the specified ADC peripheral.
  * @param  ADCx: Select the ADC peripheral.
  * @param  NewState: new state of the ADCx peripheral.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void ADC_Cmd(ADC_TypeDef *ADCx, FunctionalState NewState)
{
    if (NewState != DISABLE)
    {
        ADCx->CR_b.EN = 1;
    }
    else
    {
        ADCx->CR_b.EN = 0;
    }
}

/**
  * @brief  Enables or disables the selected ADC software start conversion .
  * @param  ADCx: Select the ADC peripheral.
  * @param  NewState: new state of the selected ADC software start conversion.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void ADC_SoftwareStartConvCmd(ADC_TypeDef *ADCx, FunctionalState NewState)
{
    if (NewState != DISABLE)
    {
        ADCx->CR_b.SWT = 1;
    }
    else
    {
        ADCx->CR_b.SWT = 0;
    }
}

/**
  * @brief  Enables or disables the specified ADC interrupts.
  * @param  ADCx: Select the ADC peripheral.
  * @param  ADC_IT: specifies the ADC interrupt sources to be enabled or disabled. 
  *   This parameter can be any combination of the following values:
  *     @arg ADC_IT_EOC: End of conversion interrupt mask
  *     @arg ADC_IT_TCOLL: ADC event conflict interrupt mask
  * @param  NewState: new state of the specified ADC interrupts.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void ADC_ITConfig(ADC_TypeDef *ADCx, uint32_t ADC_IT, FunctionalState NewState)
{
    if (NewState != DISABLE)
    {
        /* Enable the selected ADC interrupts */
        ADCx->IEN |= ADC_IT;
    }
    else
    {
        /* Disable the selected ADC interrupts */
        ADCx->IEN &= (~(uint32_t)ADC_IT);
    }
}

/**
  * @brief  Checks whether the specified ADC interrupt has occurred or not.
  * @param  ADCx: Select the ADC peripheral.
  * @param  ADC_IT: specifies the ADC interrupt source to check. 
  *   This parameter can be one of the following values:
  *     @arg ADC_IT_EOC: End of conversion interrupt mask
  *     @arg ADC_IT_TCOLL: ADC event conflict interrupt mask
  * @retval The new state of ADC_IT (SET or RESET).
  */
ITStatus ADC_GetITStatus(ADC_TypeDef *ADCx, uint32_t ADC_IT)
{
    ITStatus bitstatus = RESET;

    if ((ADCx->IPND & ADC_IT) != (uint32_t)RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/**
  * @brief  Gets the ADC queue rank output value.
  * @param  ADCx: Select the ADC peripheral.
  * @param  ADC_QueueRank: Specifies the ADC queue to be registered.
  *   This parameter can be any combination of ADC_QueueRankx where x can be (1..8).
  * @retval  ADC queue rank output value.
  */
uint16_t ADC_GetQueueRankValue(ADC_TypeDef *ADCx, uint8_t ADC_Queue_Rank)
{
    uint16_t adc_val = 0;
    switch (ADC_Queue_Rank)
    {
    case ADC_Queue_Rank1:
        adc_val = ADCx->DR1;
        break;

    case ADC_Queue_Rank2:
        adc_val = ADCx->DR2;
        break;

    case ADC_Queue_Rank3:
        adc_val = ADCx->DR3;
        break;

    case ADC_Queue_Rank4:
        adc_val = ADCx->DR4;
        break;

    case ADC_Queue_Rank5:
        adc_val = ADCx->DR5;
        break;

    case ADC_Queue_Rank6:
        adc_val = ADCx->DR6;
        break;

    case ADC_Queue_Rank7:
        adc_val = ADCx->DR7;
        break;  

    case ADC_Queue_Rank8:
        adc_val = ADCx->DR8;
        break;  

    default:
        break;
    }
    
    return adc_val;
}

/**
  * @brief  Clears the ADCx's interrupt pending bits.
  * @param  ADCx: select the ADC peripheral.
  * @param  ADC_IT: specifies the ADC interrupt pending bit to clear.
  *   This parameter can be any combination of the following values:
  *     @arg ADC_IT_EOC: End of conversion interrupt mask
  *     @arg ADC_IT_TCOLL: ADC event conflict interrupt mask
  * @retval None
  */
void ADC_ClearITPendingBit(ADC_TypeDef *ADCx, uint32_t ADC_IT)
{
    ADCx->EIPND |= ADC_IT;
}

/***************************************END OF FILE*********************************/
